import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.xml.sax.SAXException;

import java.awt.event.HierarchyBoundsAdapter;
import java.awt.event.HierarchyEvent;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * ==================================================================
 * GENERAL NOTES
 * ==================================================================
 * - The bounds of each component contained in TestCreator is calculated based
 * on  the bounds of TestCreator. e.g. the height of a component is 
 * always set to be 20% of the height of TestCreator. Likewise, the 
 * x position of a component is always set to be half of the width of
 * TestCreator minus 20 (width of component = (getWidth / 2) - 20). This
 * way, the layout and proportions of the components in TestCreator will
 * always be the same no matter what the bounds of TestCreator are.
 * ===================================================================
 *
 */

public class TestCreator extends JFrame {

	private JPanel contentPane;
	private Workspace workspace;
	private ImageGallery imageGallery;
	private Navigation navigation;
	private TestSaver testSaver;
	private TestLoader testLoader;

	/**
	 * Create the frame.
	 */
	public TestCreator() {

		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(100, 100, 833, 442);
		
		testLoader = new TestLoader();
		
		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);
		
		JMenu mnNewMenu = new JMenu("File");
		menuBar.add(mnNewMenu);
		
		JMenuItem mntmCreateNewTest = new JMenuItem("Create New Test");
		mntmCreateNewTest.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent arg0) {
				setUpWorkspace();
				workspace.createNewProblem();
			}
		});

		mnNewMenu.add(mntmCreateNewTest);
		
		final JMenuItem mntmSaveTest = new JMenuItem("Save Test");
		mntmSaveTest.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
			   if (mntmSaveTest.isEnabled()){
				   workspace.updateProblem();
				   if (!(testSaver.fileIsSet())){
			     	   JFileChooser saveDialog = new JFileChooser();
				       saveDialog.setFileFilter(new FileNameExtensionFilter("XML File", "xml"));
				       saveDialog.setAcceptAllFileFilterUsed(false);
				       int saveValue = saveDialog.showSaveDialog(getParent());
				       if (saveValue == JFileChooser.APPROVE_OPTION){
					      testSaver.setFile(saveDialog.getSelectedFile().getAbsolutePath() + ".xml");
					      try {
						      testSaver.save(workspace.getTest());
					      } catch (FileNotFoundException e) {
						      // TODO Auto-generated catch block
						      e.printStackTrace();
					      } catch (ParserConfigurationException e) {
						      // TODO Auto-generated catch block
						      e.printStackTrace();
					      } catch (TransformerException e) {
						      // TODO Auto-generated catch block
						      e.printStackTrace();
					      }
				       }
				   } else {
					      try {
						      testSaver.save(workspace.getTest());
					      } catch (FileNotFoundException e) {
						      // TODO Auto-generated catch block
						      e.printStackTrace();
					      } catch (ParserConfigurationException e) {
						      // TODO Auto-generated catch block
						      e.printStackTrace();
					      } catch (TransformerException e) {
						      // TODO Auto-generated catch block
						      e.printStackTrace();
					      }
				   }
			   }
			}
		});
		mntmSaveTest.setEnabled(false);
		mnNewMenu.add(mntmSaveTest);
		
		JMenuItem mntmLoadTest = new JMenuItem("Load Test");
		mntmLoadTest.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				JFileChooser loadDialog = new JFileChooser();
			    loadDialog.setFileFilter(new FileNameExtensionFilter("XML File", "xml"));
			    loadDialog.setAcceptAllFileFilterUsed(false);
			    int returnValue = loadDialog.showDialog(getParent(), "Load");
			    if (returnValue == JFileChooser.APPROVE_OPTION){
					try {
						Test t = testLoader.loadTest(loadDialog.getSelectedFile().getAbsolutePath());
						if (workspace == null){
							setUpWorkspace();
							workspace.loadTest(t);
				    	} else {
				    		workspace.clearWorkspace();
				    		workspace.loadTest(t);
				    	}
					} catch (ParserConfigurationException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (SAXException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			    }
			}
		});
		mnNewMenu.add(mntmLoadTest);
		
		JMenu mnEdit = new JMenu("Edit");
		menuBar.add(mnEdit);
		
		final JMenuItem mntmRemoveCurrentProblem = new JMenuItem("Remove Current Problem");
		mntmRemoveCurrentProblem.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (mntmRemoveCurrentProblem.isEnabled()){
				   int currentProblemIndex = workspace.getIndex();
				   workspace.removeProblem(currentProblemIndex);
				   workspace.clearWorkspace();
				   if (currentProblemIndex >= workspace.getSession().getNoOfProblems()){
					   workspace.loadProblem(workspace.getSession().getNoOfProblems() - 1);
				   } else {
					   workspace.loadProblem(currentProblemIndex);
				   }
			    }
			}
		});
		mntmRemoveCurrentProblem.setEnabled(false);
		mnEdit.add(mntmRemoveCurrentProblem);
		
		final JMenuItem mntmRemoveSelectedComparison = new JMenuItem("Remove Selected Comparison");
		mntmRemoveSelectedComparison.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (mntmRemoveSelectedComparison.isEnabled())
				   workspace.removeSelectedComparison();
			}
		});
		mntmRemoveSelectedComparison.setEnabled(false);
		mnEdit.add(mntmRemoveSelectedComparison);
		
		final JMenuItem mntmRemoveSession = new JMenuItem("Remove Session");
		mntmRemoveSession.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (mntmRemoveSession.isEnabled()){
					workspace.removeSession();
					navigation.updateSessionList(workspace.getTest());
				}
			}
		});
		mntmRemoveSession.setEnabled(false);
		mnEdit.add(mntmRemoveSession);
		
		final JMenuItem mntmSetToken = new JMenuItem("Set Token Reward");
		mntmSetToken.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (mntmSetToken.isEnabled()){
				   SetTokenRewarded dialog = new SetTokenRewarded (workspace.getTest().getTokenBoard(), workspace.getSession().getProblem(workspace.getIndex()));
				}
		    }
		});
		mntmSetToken.setEnabled(false);
		mnEdit.add(mntmSetToken);
		
		JMenu mnInsert = new JMenu("Insert");
		menuBar.add(mnInsert);
		
		final JMenuItem mntmNewProblem = new JMenuItem("New Problem");
		mntmNewProblem.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent arg0) {
				if (mntmNewProblem.isEnabled()){
				   workspace.updateProblem();
				   workspace.clearWorkspace();
				   workspace.createNewProblem();
				}
			}
		});
		mntmNewProblem.setEnabled(false);
		mnInsert.add(mntmNewProblem);
		
		final JMenuItem mntmNewComparison = new JMenuItem("New Comparison");
		mntmNewComparison.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (mntmNewComparison.isEnabled())
				   workspace.addComparison();
			}
		});
		mntmNewComparison.setEnabled(false);
		mnInsert.add(mntmNewComparison);
		
		final JMenuItem mntmNewSession = new JMenuItem("New Session");
		mntmNewSession.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (mntmNewSession.isEnabled()){
				   NameSessionDialog nsDialog = new NameSessionDialog(workspace, navigation);
				}
			}
		});
		mntmNewSession.setEnabled(false);
		mnInsert.add(mntmNewSession);
		
		JMenu mnSettings = new JMenu("Settings");
		menuBar.add(mnSettings);
		
		final JMenuItem mntmProblemSettings = new JMenuItem("Problem Settings");
		mntmProblemSettings.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (mntmProblemSettings.isEnabled()){
				   ProblemSettings dialog = new ProblemSettings (workspace.getCurrentProblem());
				}
			}
		});
		mntmProblemSettings.setEnabled(false);
		mnSettings.add(mntmProblemSettings);
		
		final JMenuItem sessionSettings = new JMenuItem("Session Settings");
		sessionSettings.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (sessionSettings.isEnabled()){
				   SessionSettings dialog = new SessionSettings(workspace.getSession());
				}
			}
		});
		sessionSettings.setEnabled(false);
		mnSettings.add(sessionSettings);
		
		final JMenuItem tokenBoardSettings = new JMenuItem("Token Board Settings");
		tokenBoardSettings.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (tokenBoardSettings.isEnabled()){
				   TokenBoardSettings dialog = new TokenBoardSettings(workspace.getTest().getTokenBoard());
				}
			}
		});
		tokenBoardSettings.setEnabled(false);
		mnSettings.add(tokenBoardSettings);
		
		final JMenuItem delaySettings = new JMenuItem("Delay Settings");
		delaySettings.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (delaySettings.isEnabled()){
				   DelaySettings dialog = new DelaySettings(workspace.getTest());
				}
			}
		});
		delaySettings.setEnabled(false);
		mnSettings.add(delaySettings);
		
		JMenu mnRun = new JMenu("Preview");
		menuBar.add(mnRun);
		
		final JMenuItem mntmPreviewTest = new JMenuItem("Preview Test");
		mntmPreviewTest.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent arg0) {
				if (mntmPreviewTest.isEnabled()){
				   workspace.updateProblem();
				   //TestRunner testRunner = new TestRunner(workspace.getTest());
				}
			}
		});
		mntmPreviewTest.setEnabled(false);
		mnRun.add(mntmPreviewTest);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		setVisible (true);
	}
	
	public void setUpWorkspace (){
		testSaver = new TestSaver();
		navigation = new Navigation(0, 0, 231, contentPane.getHeight());
		navigation.addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
			@Override
			public void ancestorResized(HierarchyEvent arg0) {
				navigation.setBounds(0, 0, 231, contentPane.getHeight());
			}
		});
		contentPane.add(navigation);
		workspace = new Workspace(navigation.getWidth(), 0, contentPane.getWidth() - 231 - navigation.getWidth(), contentPane.getHeight(), navigation);
		workspace.addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
			@Override
			public void ancestorResized(HierarchyEvent arg0) {
				workspace.setBounds(navigation.getWidth(), 0, contentPane.getWidth() - 231 - navigation.getWidth(), contentPane.getHeight());
				if (workspace.getComponentCount() > 0){
				   workspace.resizeProblem();
				}
			}
		});
		contentPane.add(workspace);
		workspace.updateUI();
		navigation.setWorkspace(workspace);
		navigation.updateSessionList(workspace.getTest());
		
		imageGallery = new ImageGallery(workspace.getWidth() + navigation.getWidth(), 0, 231, contentPane.getHeight());
		imageGallery.addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
			@Override
			public void ancestorResized(HierarchyEvent arg0) {
				imageGallery.setBounds(workspace.getWidth() + navigation.getWidth(), 0, 231, contentPane.getHeight());
			}
		});
		contentPane.add(imageGallery);
		contentPane.updateUI();
		
		workspace.setImageGallery(imageGallery);
		imageGallery.setWorkspace(workspace);
		
		final JMenuBar menuBar = getJMenuBar();
		menuBar.getMenu(0).getMenuComponent(1).setEnabled(true);
		menuBar.getMenu(2).getMenuComponent(0).setEnabled(true);
		menuBar.getMenu(2).getMenuComponent(1).setEnabled(true);
		menuBar.getMenu(2).getMenuComponent(2).setEnabled(true);
		menuBar.getMenu(3).getMenuComponent(0).setEnabled(true);
		menuBar.getMenu(3).getMenuComponent(1).setEnabled(true);
		menuBar.getMenu(3).getMenuComponent(2).setEnabled(true);
		menuBar.getMenu(3).getMenuComponent(3).setEnabled(true);
		menuBar.getMenu(4).getMenuComponent(0).setEnabled(true);
		
		menuBar.getMenu(1).addMouseListener(new MouseAdapter() {
			@Override
			public void mouseEntered(MouseEvent arg0) {
				if (workspace.getSelectedButtonType() != 2 || workspace.getSession().getProblem(workspace.getIndex()).getNoOfComparisons() <= 2){
					menuBar.getMenu(1).getMenuComponent(1).setEnabled(false);
				} else {
					menuBar.getMenu(1).getMenuComponent(1).setEnabled(true);
				}
				if (workspace.getSession().getNoOfProblems() <= 1){
					menuBar.getMenu(1).getMenuComponent(0).setEnabled(false);
				} else {
					menuBar.getMenu(1).getMenuComponent(0).setEnabled(true);
				}
				if (workspace.getNoOfSessions() <= 1){
					menuBar.getMenu(1).getMenuComponent(2).setEnabled(false);
				} else {
					menuBar.getMenu(1).getMenuComponent(2).setEnabled(true);
				}
				if (workspace.getSession().isRewardedPhase() && workspace.getTest().getTokenBoard().getNoOfTokens() > 0){
					menuBar.getMenu(1).getMenuComponent(3).setEnabled(true);
				} else {
					menuBar.getMenu(1).getMenuComponent(3).setEnabled(false);
				}
			}
		});
	}
}
